package sch.frog.utils.mail;

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import com.sun.mail.util.MailSSLSocketFactory;

/**
 * @author frogif
 * 依赖jar包:
  		<dependency>
	  		<groupId>javax.mail</groupId>
	  		<artifactId>mail</artifactId>
	  		<version>1.4.5</version>
	  	</dependency>
 *
 */
public final class MailSender {
	private MailSender(){}	//使MailSender不能对外提供构造方法
	
	private Session session;	//邮件会话对象
	
	/**
	 * 创建邮件发送对象
	 * @param host	邮件发送服务主机
	 * @param username 用户名
	 * @param password 密码
	 * @return
	 * @throws GeneralSecurityException 
	 */
	public static MailSender getInstance(String host, final String username, final String password) throws GeneralSecurityException{
		Properties props = new Properties();
		props.setProperty("mail.smtp.host", host);	//指定邮件服务器主机
		props.setProperty("mail.smtp.auth", "true");	//指定客户端是否向邮件服务器提交认证
		
		//ssl认证, QQ邮箱发送邮件必须要有
		MailSSLSocketFactory sf = new MailSSLSocketFactory();
		sf.setTrustAllHosts(true);
		props.put("mail.smtp.ssl.enable", "true");
		props.put("mail.smtp.ssl.socketFactory", sf);
		
		//创建验证器
		Authenticator auth = new Authenticator() {
			public PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(username, password);
			}
		};
		
		MailSender mailSender = new MailSender();
		mailSender.session = Session.getInstance(props, auth);	//创建邮件会话对象
		
		return mailSender;
	}
	
	/**
	 * 发送邮件
	 * @param mail 邮件对象
	 * @return
	 * @throws MessagingException
	 * @throws IOException
	 */
	public boolean sendMail(Mail mail) throws MessagingException, IOException {
		Message message = new MimeMessage(session);	//创建邮件对象
		
		message.setFrom(new InternetAddress(mail.getFrom()));	//设置发件人
		message.addRecipient(RecipientType.TO, new InternetAddress(mail.getToAddress()));	//设置收件人
		message.addHeader("charset", "UTF-8");
		message.setSubject(mail.getSubject());	//设置邮件主题
		
		// 设置抄送
		String[] cc = mail.getCcAddress();
		if (cc != null) {
			Address[] ccAddressArray = new InternetAddress[cc.length];
			for(int i = 0; i < cc.length; i++){
				ccAddressArray[i] = new InternetAddress(cc[i]);
			}
			message.addRecipients(RecipientType.CC, ccAddressArray);
		}

		// 设置暗送
		String[] bcc = mail.getBccAddress();
		if (bcc != null) {
			Address[] bccAddressArray = new InternetAddress[bcc.length];
			for(int i = 0; i < bcc.length; i++){
				bccAddressArray[i] = new InternetAddress(bcc[i]);
			}
			message.addRecipients(RecipientType.BCC, bccAddressArray);
		}
		
		MimeMultipart parts = new MimeMultipart();// 创建部件集对象
		
		// 设置邮件正文
		MimeBodyPart contentPart = new MimeBodyPart();// 创建一个部件, 存放邮件正文
		contentPart.setText(mail.getContent()); 	//将文件内容放入文本 
        contentPart.setHeader("Content-Type", "text/html;charset=utf-8"); //设置 contentPart的类型为邮件文本
        parts.addBodyPart(contentPart);	//将邮件文本内容添加到邮件文本
        
        List<AttachFile> fileList = mail.getFileList();
        for (AttachFile attachFile : fileList) {
        	
        	MimeBodyPart attachBody = new MimeBodyPart();
        	
        	File file = attachFile.getFile();
        	attachBody.attachFile(file);	//添加附件文件
       		attachBody.setFileName(MimeUtility.encodeText(attachFile.getFileName())); //设置附件名
        	
        	if(attachFile.getCid() != null){
        		attachBody.setContentID(attachFile.getCid());	//设置cid
        	}
        	
        	//添加附件部件到部件集中
        	parts.addBodyPart(attachBody);
		}
		
        message.setContent(parts);
        message.setSentDate(new Date());  
        message.saveChanges();
        
        Transport.send(message);
        
		return true;
	}
	
}
